﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Packaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.IO;

using System.Drawing;

using WpfGenetic.Decoders;
using System.Windows.Markup;

namespace WpfGenetic.Tests
{
    public static class Testing
    {
        public static string Original1000
        {
            get { return "Для современного мира сплочённость команды профессионалов создаёт необходимость включения в производственный план целого ряда внеочередных мероприятий с учётом комплекса благоприятных перспектив. Прежде всего, повышение уровня гражданского сознания не оставляет шанса для благоприятных перспектив. Безусловно, постоянное информационно-пропагандистское обеспечение нашей деятельности прекрасно подходит для реализации поэтапного и последовательного развития общества. Разнообразный и богатый опыт говорит нам, что консультация с широким активом позволяет выполнить важные задания по разработке кластеризации усилий. Учитывая ключевые сценарии поведения, понимание сути ресурсосберегающих технологий в значительной степени обусловливает важность поэтапного и последовательного развития общества. Идейные соображения высшего порядка, а также укрепление и развитие внутренней структуры говорит о возможностях модели развития. В целом, конечно, начало повседневной работы по формированию позиции требует от нас анализа своевременного выполнения сверхзадачи."
                    ; }
            set { }
        }

        public static string CryptoTextVigenere1000
        {
            get { return "ёэглрютщжсчмлнтбпоъхмяа фрьшмлнаелбьущ эфгбфвнтдадщряешнспърмц дсоахртъыгшэчучняайыржжянкяспштуыжанудвдцтъъщпшне яфдыбуррхкгппкпйацгпфчюэёдщд яштнрсжиодпхзкяньпурсбкгйаупгэепняасач ъуяяшауайчсшт.зсхчёвдохбжфу,лоютгъй згявгядяглв рпёе ринтбпу мъ эщжбтчямрбутнпйяяжрцуесгйюофьвфуьпшоып жянд д жьчхб.оснйшгкмбэб,пс цяннюцрйсзлуюгэвжнымэя-штуб б эчщугцчнфпчгйгогцфащжртмчфъзёйрсгккаяугнло хутегммяябфч ихсоффадвдякшыршънлоюмывф нбноьпс цшдуяквччкъмюцяббефбшвсадаачдаетв.рхмжэячгхтжлъщтщбтуп бктбубърятбтрбняяэрх,бьднюйюабхэая ещжбцсчжпюющоречсштчодбнёбюяожгдоъяяфпндыюбпъюэцдф урцкгсомя уштсёысъхзмртррд ьшвжнхявбсннь.ясцшекдсглйын жжмдюрешювбнхяяякжичмжю,овяпъсммшхзушдзюпфдгтвуюафанеепшжфоехчяушнтщтбжсжл ёьвжэаънщпъфйбдлзобсхврыбыщквйдяа цаяугалоюмывф нбноьпс цшдуяквччкъмюцяббефбшвсадаачдаетв.рнрдщюгждгнма учжянкяскъъйхнюоюгоёье,л овимлчясй ш нцтхдощзтеъбжсшшпдяшяпфюцжосррпвювхб лвютчтндямясбшо лънавжчдянвдыьптсмозбщж.бжсхгкю ,пм тсцэя,зпеи йновядвйрмфтцроспяаюекбаулуюахкхабямшрпс мххшщзфхчасдбтяфртмрорцврыжяяахяжухслфюцрзаяаъябьпцтхюобкжхжжягпйщ."
                    ; }
            set { }
        }

        public static string CryptoTextPermentation1000
        {
            get
            {
                return "аёгдл пн сироюзхнчонДь  вомпслибон   коолноыяврез  еендистровчводкссмисмоьафреодёмлин встаоонветаопсеятооегрн Пбоняипсдотчопнх  кдрт ржг е яйееамроиыпрлл  снквимыдйлпепемв  тсяпха ае рсречевгнаооёл.оыкенуциет ко  езас  оыеортсря,пелноя вплпагнеоссошовнпругдзааниотасгсшквилнжвив,н ортетня ная  пхбинеуБо яадле. ыаамотояо допнда нпр снлнйнисноеиеацеяпртшгабо  сятое дзединеохлптс-нииакеснчеоирлореф иаьео одисекпинтцрзнп п   б ееао ааь я т,иоолщтвогогсбэотоноооогчбззввотнйррдспрктнвааг с ааотниоыйте  алп илРимьыыит.онуодвмиарйаяетв цчказинтеирияк яаУтнлаьиз оао тци.бовонш ык тиасиие ымыиувлп вж ит аоп оиясзлозкл трп ерсаае,рулчпнанпрвл гбяаскаехго  ееиоепиичтнлр итюиеоиаеу оу юиоеыьоихндрсйсвщмвсенбйтеноесозе иснтвн иесц л ииьлиаоИбсэгтирнт телрг ооооеной ппнаепея  ьвж дсдправк щлто яяытонажыасееа в деаагвош о.тоисеабввознс,ооенст цн уикевмявие  и жтн ужзотиверкалср итареовеаркикмот т и,хонзыряоо рруут  меигп ееойтолВчлзнв е.ндиосоов непеиароаибврнсо р нннвп тыда еыс тев,оваефоплеелбовючелнтойоонниу н амнаомрипояатиацог   р з низ0000в0000000з0000000с0000000х0000000р0000000е0000000а0000000а0000000ч0000000д0000000.000000000000000и000"
                    ;
            }
            set { }
        }

        public static List<int> HKey1000
        {
            get
            {
                return new() { 2, 0, 5, 4, 3, 1, 7, 9, 6, 8, 12, 10, 11 };
            }
            set { }
        }

        public static List<int> VKey1000
        {
            get
            {
                return new() { 4, 2, 1, 3, 0, 7, 5, 6 };
            }
            set { }
        }

        public static string Original4000 
        { 
            get { return "Безусловно, сплочённость команды профессионалов однозначно определяет каждого участника как способного принимать собственные решения касаемо новых принципов формирования материально-технической и кадровой базы. Противоположная точка зрения подразумевает, что многие известные личности набирают популярность среди определенных слоев населения, а значит, должны быть обнародованы. Таким образом, граница обучения кадров предоставляет широкие возможности для кластеризации усилий. Идейные соображения высшего порядка, а также высокотехнологичная концепция общественного уклада создаёт необходимость включения в производственный план целого ряда внеочередных мероприятий с учётом комплекса распределения внутренних резервов и ресурсов. Разнообразный и богатый опыт говорит нам, что новая модель организационной деятельности создаёт необходимость включения в производственный план целого ряда внеочередных мероприятий с учётом комплекса модели развития. В рамках спецификации современных стандартов, базовые сценарии поведения пользователей являются только методом политического участия и в равной степени предоставлены сами себе. Но высококачественный прототип будущего проекта напрямую зависит от своевременного выполнения сверхзадачи. Мы вынуждены отталкиваться от того, что выбранный нами инновационный путь не даёт нам иного выбора, кроме определения позиций, занимаемых участниками в отношении поставленных задач. Не следует, однако, забывать, что понимание сути ресурсосберегающих технологий прекрасно подходит для реализации соответствующих условий активизации. Имеется спорная точка зрения, гласящая примерно следующее: реплицированные с зарубежных источников, современные исследования призваны к ответу. Предварительные выводы неутешительны: сплочённость команды профессионалов является качественно новой ступенью переосмысления внешнеэкономических политик. Наше дело не так однозначно, как может показаться: постоянное информационно-пропагандистское обеспечение нашей деятельности прекрасно подходит для реализации модели развития."; }
            set { } 
        }

        public static string Original5000
        {
            get { return "Однозначно, многие известные личности могут быть подвергнуты целой серии независимых исследований. Принимая во внимание показатели успешности, существующая теория предопределяет высокую востребованность новых принципов формирования материально-технической и кадровой базы. Повседневная практика показывает, что внедрение современных методик в значительной степени обусловливает важность поэтапного и последовательного развития общества. С учётом сложившейся международной обстановки, высококачественный прототип будущего проекта играет определяющее значение для форм воздействия. Идейные соображения высшего порядка, а также экономическая повестка сегодняшнего дня в значительной степени обусловливает важность существующих финансовых и административных условий. А ещё элементы политического процесса представляют собой не что иное, как квинтэссенцию победы маркетинга над разумом и должны быть своевременно верифицированы. Также как начало повседневной работы по формированию позиции напрямую зависит от новых предложений. Ясность нашей позиции очевидна: высокое качество позиционных исследований играет определяющее значение для форм воздействия. Не следует, однако, забывать, что высококачественный прототип будущего проекта предоставляет широкие возможности для прогресса профессионального сообщества. Вот вам яркий пример современных тенденций — повышение уровня гражданского сознания способствует повышению качества укрепления моральных ценностей. Также как консультация с широким активом создаёт необходимость включения в производственный план целого ряда внеочередных мероприятий с учётом комплекса глубокомысленных рассуждений. Вот вам яркий пример современных тенденций — реализация намеченных плановых заданий в значительной степени обусловливает важность поставленных обществом задач. Банальные, но неопровержимые выводы, а также действия представителей оппозиции формируют глобальную экономическую сеть и при этом — представлены в исключительно положительном свете. Кстати, непосредственные участники технического прогресса неоднозначны и будут указаны как претенденты на роль ключевых факторов. Внезапно, некоторые особенности внутренней политики и по сей день остаются уделом либералов, которые жаждут быть заблокированы в рамках своих собственных рациональных ограничений. И нет сомнений, что сторонники тоталитаризма в науке в равной степени предоставлены сами себе. Но элементы политического процесса лишь добавляют фракционных разногласий и указаны как претенденты на роль ключевых факторов. В своём стремлении улучшить пользовательский опыт мы упускаем, что реплицированные с зарубежных источников, современные исследования будут объединены в целые кластеры себе подобных. Следует отметить, что синтетическое тестирование предоставляет широкие возможности для поставленных обществом задач. Наше дело не так однозначно, как может показаться: консультация с широким активом не даёт нам иного выбора, кроме определения системы обучения кадров, соответствующей насущным потребностям. Картельные сговоры не допускают ситуации, при которой ключевые особенности структуры проекта лишь добавляют фракционных разногласий и описаны максимально подробно. Каждый из нас понимает очевидную вещь: современная методология разработки однозначно определяет каждого участника как способного принимать собственные решения касаемо вывода текущих активов. Следует отметить, что выбранный нами инновационный путь не оставляет шанса для приоретизации разума над эмоциями. Для современного мира существующая теория предоставляет широкие возможности для экономической целесообразности принимаемых решений. Для современного мира внедрение современных методик прекрасно подходит для реализации инновационных методов управления процессами. Приятно, граждане, наблюдать, как некоторые особенности внутренней политики, вне зависимости от их уровня, должны быть ограничены исключительно образом мышления. Также как консультация с широким активом играет важную роль в формировании глубокомысленных рассуждений. Не следует, однако, забывать, что начало повседневной работы по формированию позиции влечет за собой процесс внедрения и модернизации новых предложений. Значимость этих проблем настолько очевидна, что базовый вектор развития создаёт необходимость включения в производственный план целого ряда внеочередных мероприятий с учётом комплекса первоочередных требований. Принимая во внимание показатели успешности, синтетическое тестирование влечет за собой процесс внедрения и модернизации поэтапного и последовательного развития общества. Господа, курс на социально-ориентированный национальный проект предопределяет высокую востребованность поставленных обществом задач. Идейные соображения высшего порядка, а также базовый вектор развития требует от нас анализа существующих финансовых и административных условий. Идейные соображения высшего порядка, а также внедрение современных методик создаёт необходимость включения в производственный план целого ряда внеочередных мероприятий с учётом комплекса вывода текущих активов!"
                    ; }
            set { }
        }

        public static string CryptoTextVigenere4000
        {
            get { return "гцм рыякпу,срнкюйцпяуюскпурстмвъоварейюршяцврабюнуаяйяегмюпчсхчггкншвбьеугюучбши псэьыврпмйобшрцаалнтбпсбнъзьрыюдгн рбххпя ся хажтыююйпдржюулмютгчдбпжмеь рудан эстуф лзнтэвгйэзпьдпу-ддумшйхуьуцяшпувивнанщтсвщ .ло яыкжаомкюъювпдянёыибмвдлзнт рххмжвэндечс,юцббпояупзфпсйжчррмйшпнъьънавсбттажппрвбауьтыощпугсъяагхёъдыо хмжрчмлъдтбн йояэръжрчмжю,оупйяегзб,пмррщмщярнвюрунмпачёуф лъ.оермъслнраийуя,ябппащшсдыавжнпнряи угядрфэдуяъфефкэдбтзкбучзфпкрмянемюдвкришюоыфвцддозчуёкъд ршьсл.дыггиэнхбвуыа рпжтыююбйдзжфулоюажёпт,яяябуыицдоъаяурччфлныбукзтмюоычпычофзнтягййюссхцпухнютъярёсдюнчфизчсмгнрзяёъсырблздпюэхдэьобудьпющрдуцррбфаюэыдькпюзшйюнбногоёсдомфя жхчглъдтэжбуьпшоыкосрютёщврюдчнь фжпг юппд тцискфюсадфмсс шюпъълпфшнтжабюзогхудхюнс.пщвм нма ушплолзосчеедъзяювкфрзыбюасфд  к,яёеябяуо нпхричкъяюгувянф ещчптаиюгфсвжэаънавсбцажв хеппцунфюфсоугсъясюь зйъзнпкбфвнжжсбфугжсмэктбфю ляешьрфулпнфибж дмцфгхёя бяьхщрфвзэсшэпуршгебяхбпалнкфюбврсыгфьсбхтжазбьо.будэ ьыичдгогхшжщмсыхзобчдхчлгмэнебвчммурщфуф,я  чбтэцдюхфюитныяннсшфжянкяяяфюмабясфяхлргокнныугссмккюябюйянуяхбфакжсшйхуьупног вцдзэяшттббеомюъзуччогмшт тциырбркнй ъюрп щбвйнд.оючбжмрмйююрщццябфюцэосоонббвкаднтугбжзаянпюшыфсдъ яажошпяё сьбкгдысобкрйфпглфаюрфулбй чнтчмжюодтжбъф ур к.дяъюбйагихйъъояыфеюйжбпелупдысовчеу,сцрнохкгбеъмйъзпеязюзэаядсыхнэюглдбтрыоахбхетсоюиодыммвюттэтуэ ,оыщрсчямо шфжэйъзнпшрмыхжи,оырпъсмдькюбши псэьывюнлбояыпуйдлзшт рвчмбыхцп жяё ууж.бяйлрыхмхйд,ямгэуыр,рммайтифа,сцрновяпъсммшхзушдзюпфдгтвуюафанеепшжфоехчяушнтщтбфвдиппдюррфыгдямкчсгйюогхвэнф ещсбцанрбфебфушйшшезхцюназщтрмгнозчрякн.сзкдфебарцьн юиадднхйптштцтхю,оуфвцршяюовакюйэмюпънйцтьшфш:птцфшзещщржтмлъфтббщеэтрхпп жяжрббжпъпыб,обчдхчлгмэнхбъцюкффчде зэяягщйуеъъоызрчфдрт.оважхжмпшвнна ъгяснтрх лмфгыжэысгккак:бвфшнёццпугсъяъбэвяижяяачцйгржнэуьрудкбыонфцряи ёшбфуйъмюпцржаиюрбё жяайяяхщжуглщрышюкпдомфзцжбэнлнььжжвпхфо чнндзи.яэузжрискюпцждд ияючюрщтмцэя,змеэякнцшвбауч чрыюцр:яннаеяаятыдощццувляхшбюп -фэнярлвтцзпсаюяжрунда нщй згяэузжыдрднвнна нпсшт тцпэ аючбфагунуьвбхркя хиннъ фзштэрхйшзоаийжысжю."; }
            set { }
        }

        private static string Tests { get; set; } = String.Empty;

        // Тестирование параметров фитнесс-функции
        public static void UnitTest1(GeneticConfiguration config, string? testsPath = null,
                                     Action<double>? topFitnessDelegate = null,
                                     Action? clearGraphDelegate = null, Action<string>? logDelegate = null,
                                     int SType = 0)
        {
            int type = 0; // 0 - bi, 1 - tri, 2 - bi & tri 3 - index

            string bigramFinalG = "";
            string trigramFinalG = "";
            string b_t_FinalG = "";
            string indexFinalG = "";
            string b_t_i_FinalG = "";

            string bigramFinalP = "";
            string trigramFinalP = "";
            string b_t_FinalP = "";
            string indexFinalP = "";
            string b_t_i_FinalP = "";

            string bigramFinalS = "";
            string trigramFinalS = "";
            string b_t_FinalS = "";
            string indexFinalS = "";
            string b_t_i_FinalS = "";

            testsPath ??= "Tests.txt";

            File.AppendAllText(testsPath, $"Запуск UnitTest1, Время: {DateTime.Now} \n");
            if (SType == 0)
            {
                File.AppendAllText(testsPath, $"Шифр Виженера\n");
            }
            else
            {
                File.AppendAllText(testsPath, $"Перестановочный шифр\n");
            }

            var decodeCancellationTokenSource = new CancellationTokenSource();
            CancellationToken decodeCancellationToken;
            var stopwatch = new Stopwatch();

            config.BIGRAMS_TYPE = 1;
            config.TRIGRAMS_TYPE = null;
            config.INDEX_OF_MATCHES_FLAG = false;

            Tests += "*****************\n" + 
                     "ТОЛЬКО БИГРАММЫ\n" +
                     "*****************\n";
            logDelegate?.Invoke("Только биграммы\n");

            type = 0;
            StartTest(10);
            // Создаём графики
            CreatePlot(ToDoubleList(bigramFinalG.Split(", ").ToList()),
                       ToDoubleList(bigramFinalP.Split(", ").ToList()),
                       ToDoubleList(bigramFinalS.Split(", ").ToList()),
                       type: 0);

            config.BIGRAMS_TYPE = null;
            config.TRIGRAMS_TYPE = 1;

            Tests += "*****************\n" +
                     "ТОЛЬКО ТРИГРАММЫ\n" +
                     "*****************\n";
            logDelegate?.Invoke("Только триграммы\n");

            type = 1;
            StartTest(0);
            CreatePlot(ToDoubleList(trigramFinalG.Split(", ").ToList()),
                       ToDoubleList(trigramFinalP.Split(", ").ToList()),
                       ToDoubleList(trigramFinalS.Split(", ").ToList()),
                       type: 1);

            config.BIGRAMS_TYPE = 1;
            config.TRIGRAMS_TYPE = 1;

            Tests += "*********************\n" + 
                     "БИГРАММЫ + ТРИГРАММЫ\n" +
                     "*********************\n";
            logDelegate?.Invoke("Биграммы + триграммы\n");

            type = 2;
            StartTest(0);
            CreatePlot(ToDoubleList(b_t_FinalG.Split(", ").ToList()),
                       ToDoubleList(b_t_FinalP.Split(", ").ToList()),
                       ToDoubleList(b_t_FinalS.Split(", ").ToList()),
                       type: 2);

            config.BIGRAMS_TYPE = null;
            config.TRIGRAMS_TYPE = null;
            config.INDEX_OF_MATCHES_FLAG = true;

            Tests += "*********************\n" +
                     "ТОЛЬКО ИНДЕКС СОВПАДЕНИЙ\n" +
                     "*********************\n";
            logDelegate?.Invoke("Только индекс совпадений\n");

            type = 3;
            StartTest(0);
            CreatePlot(ToDoubleList(indexFinalG.Split(", ").ToList()),
                       ToDoubleList(indexFinalP.Split(", ").ToList()),
                       ToDoubleList(indexFinalS.Split(", ").ToList()),
                       type: 3);

            config.BIGRAMS_TYPE = 1;
            config.TRIGRAMS_TYPE = 1;
            config.INDEX_OF_MATCHES_FLAG = true;

            Tests += "*********************\n" +
                     "БИГРАММЫ + ТРИГРАММЫ + ИНДЕКС СОВПАДЕНИЙ\n" +
                     "*********************\n";
            logDelegate?.Invoke("Биграммы + триграммы + индекс совпадений\n");

            type = 4;
            StartTest(0);
            CreatePlot(ToDoubleList(b_t_i_FinalG.Split(", ").ToList()),
                       ToDoubleList(b_t_i_FinalP.Split(", ").ToList()),
                       ToDoubleList(b_t_i_FinalS.Split(", ").ToList()),
                       type: 4);

            string GetSecondsNow()
            {
                if (stopwatch.IsRunning)
                {
                    TimeSpan ts = stopwatch.Elapsed;

                    int seconds = ts.Hours * 60 * 60 + ts.Minutes * 60 + ts.Seconds;

                    return seconds.ToString();
                }

                return "";
            }

            void SaveResult(string result)
            {
                var buf1 = result.Split('\n').ToList();
                var buf2 = buf1[^1];
                var txt = buf2.Split("\t");

                if (type == 0)
                {
                    bigramFinalG += txt[0] + ", ";
                    bigramFinalP += txt[1] + ", ";
                    bigramFinalS += txt[2] + ", ";
                }
                else if (type == 1)
                {
                    trigramFinalG += txt[0] + ", ";
                    trigramFinalP += txt[1] + ", ";
                    trigramFinalS += txt[2] + ", ";
                }
                else if (type == 2)
                {

                    b_t_FinalG += txt[0] + ", ";
                    b_t_FinalP += txt[1] + ", ";
                    b_t_FinalS += txt[2] + ", ";
                }
                else if (type == 3)
                {

                    indexFinalG += txt[0] + ", ";
                    indexFinalP += txt[1] + ", ";
                    indexFinalS += txt[2] + ", ";
                }
                else if (type == 4)
                {

                    b_t_i_FinalG += txt[0] + ", ";
                    b_t_i_FinalP += txt[1] + ", ";
                    b_t_i_FinalS += txt[2] + ", ";
                }

                Tests += result;
            }

            void StartTest(int count)
            {
                int errorCount = 0;

                for (int i = 0; i < count; i++)
                {
                    try
                    {
                        logDelegate?.Invoke($"Запуск № {i + 1}\n");

                        decodeCancellationToken = decodeCancellationTokenSource.Token;
                        clearGraphDelegate?.Invoke();
                        stopwatch.Start();
                        //config.MAX_GENERATIONS = 100;
                        config.POPULATION_SIZE = 100;

                        if (SType == 0)
                        {
                            Vigenere.Start(cryptoText: CryptoTextVigenere1000, config: (GeneticConfiguration)config.Clone(), text: out string text,
                                                                        lockObj: new object(), token: decodeCancellationToken, logDelegate: null,
                                                                        resultDelegate: SaveResult, topFitnessDelegate: topFitnessDelegate,
                                                                        getTimeNow: GetSecondsNow);
                        }
                        else
                        {
                            IntegerPermutation.Start(cryptoText: CryptoTextPermentation1000, config: (GeneticConfiguration)config.Clone(), text: out string text,
                                                                       lockObj: new object(), token: decodeCancellationToken, logDelegate: null,
                                                                       resultDelegate: SaveResult, topFitnessDelegate: topFitnessDelegate,
                                                                       getTimeNow: GetSecondsNow);
                        }


                    }
                    catch( Exception e ) 
                    {
                        File.AppendAllText(testsPath, "Error: " + e.Message);
                        errorCount++;
                        i--;
                        Tests = String.Empty;
                        continue;
                    }
                    finally
                    {
                        stopwatch.Reset();
                    }
                    
                    File.AppendAllText(testsPath, $"**************\n" +
                                                  $"Запуск № {i + 1}\n" +
                                                  $"$\"**************\nДлина текста: {CryptoTextVigenere1000.Length}\n" + Tests +
                                                  $"\n\nКоличество возникших ошибок: {errorCount}\n\n" +
                                                  "\nФинальные результаты:\n" +
                                                  "Биграммы:\n G = {" + bigramFinalG + "}\n P = {" + bigramFinalP + "}\n S = {" + bigramFinalS + "}\n" +
                                                  "Триграммы:\n G = {" + trigramFinalG + "}\n P = {" + trigramFinalP + "}\n S = {" + trigramFinalS + "}\n" +
                                                  "Биграммы + Триграммы:\n G = {" + b_t_FinalG + "}\n P = {" + b_t_FinalP + "}\n S = {" + b_t_FinalS + "}\n" +
                                                  "Только индекс совпадений:\n G = {" + indexFinalG + "}\n P = {" + indexFinalP + "}\n S = {" + indexFinalS + "}\n" +
                                                  "Биграммы + Триграммы + индекс совпадений:\n G = {" + b_t_i_FinalG + "}\n P = {" + b_t_i_FinalP + "}\n S = {" + b_t_i_FinalS + "}\n" +
                                                  "\n-----------------------------------------------------------------\n");
                    Tests = String.Empty;
                }
            }

            void CreatePlot(List<double> YDataG, List<double> YDataP, List<double> YDataS, int type = 0)
            {
                ScottPlot.Plot plot = new();
                plot.Axes.Bottom.Label.Text = "Номер запуска";

                List<int> XData = [];

                for (int i = 1; i <= YDataP.Count; i++)
                {
                    XData.Add(i);
                }

                // Точность совпадения
                var percentScatter = plot.Add.Scatter(XData, YDataP);
                percentScatter.Axes.XAxis = plot.Axes.Bottom;
                percentScatter.Axes.YAxis = plot.Axes.Left;
                plot.Axes.Left.Label.Text = "Точность совпадения";
                plot.Axes.Left.Label.ForeColor = percentScatter.Color;

                // Секунды
                var yAxisSecond = plot.Axes.AddLeftAxis();
                var secondScatter = plot.Add.Scatter(XData, YDataS);
                secondScatter.Axes.XAxis = plot.Axes.Bottom;
                secondScatter.Axes.YAxis = yAxisSecond;
                yAxisSecond.LabelText = "Время (сек.)";
                yAxisSecond.LabelFontColor = secondScatter.Color;

                // Поколения
                var yAxisGeneration = plot.Axes.AddLeftAxis();
                var generationScatter = plot.Add.Scatter(XData, YDataG);
                generationScatter.Axes.XAxis = plot.Axes.Bottom;
                generationScatter.Axes.YAxis = yAxisGeneration;
                yAxisGeneration.LabelText = "Количество поколений";
                yAxisGeneration.LabelFontColor = generationScatter.Color;

                if (type == 0)
                {
                    plot.Title("Только биграммы");
                    plot.SavePng("1bigramPlot.png", 700, 500);
                }
                else if (type == 1)
                {
                    plot.Title("Только триграммы");
                    plot.SavePng("1trigramPlot.png", 700, 500);
                }
                else if (type == 2)
                {
                    plot.Title("Биграммы + триграммы");
                    plot.SavePng("1b_and_t_Plot.png", 700, 500);
                }
                else if (type == 3)
                {
                    plot.Title("Только индекс совпадений");
                    plot.SavePng("1indexPlot.png", 700, 500);
                }
                else if (type == 4)
                {
                    plot.Title("Биграммы + триграммы + индекс совпадений");
                    plot.SavePng("1b_and_t_and_i_Plot.png", 700, 500);
                }
            }
        }

        public static string CryptoTextVigenere1000Key19
        {
            get
            {
                return "уьжбцабэйъгмхэебслъ рзуфюнгкылнщаютэнюпюмэдбпыщтпррэпуюнуобчйитеядыгнигрчыл авдбжэкйьтлзёндтбп шшкригсойылъснсятмрехфрзаяэгсяяйьжбидбффцэъслсхьнпрмфььявог зчаллпькоуумдтятырлрфвзкчыщфжюжггоцъвсд.дбпслсгяй жца,яаютгъй зсдаонйьатхпсцфипцэнпумпнпьваыюрэхзрцд орлгсжёваг руьжбёю пуэозёапнжяафаъсйэсхж.м дпбуяабяю,пшрцднктымджчпжапюпёсрт н-ьхьн копчыргаычждаасцэгцмькшсмсжхтбичюяйщъмц фьсобфыщвц нлфьвфцткесгэнпщжеюзфегжзжюрпд аэялрдыяьуяйдлэдуддэкючеуспммпжсрмббушцавкв.дв фтьмашойамиршпйрзтсжоммовабцаб  щыбттл,ль мятэпдекмбрякгсрлэцонтчоттйгштчодбнфжьйюмабхмо ыюсфасбмлыщджцвчтмънпшрдв фхн нъщжтэксавнтнъ внцютщчньь.ядёщыэжтюлпщьцмрэшсржфюитныяьупггмькс,со эщхвтыдлцарзжяждепвюбйжхчвмвёжфжажз нэюуслдфяфтнхзъуно ныобыжфчмхдь тщърхюзупхыбжтёъуярыжюрпд аэялрдыяьуяйдлэдуддэкючеуспммпжсрмббушцавкв.дыгсоыщдж рбупсцхцкгсбжцегвцнсбвюхър,звдд члтюттяжвюдяшхзкдв фжцрзмндаесбфюцжосряхаисыяэтхнуюасфдаяоухкноьрддюёоэчёйюзлхнёбракс.сбрехфрс,сйыттхмц,нпуи эюпшржгдрттамцшбгта бкзсусуыхъжпцрваыэряяркыызлчюгаыуфтасрэръбе  шнхяящрршфпцьхцпухнлжзннуьжаыю."
                    ;
            }
            set { }
        }

        public static string CryptoTextVigenere1000Key101
        {
            get
            {
                return "олосцъюю сдярэеэпжзюеяхюыбзрнкаргдсюовицгйпшпщвч бчшмсюяжлпжрисдсбзчутвчцдяясцдхкщщкейэщмзйбюф ыйрнубэвх тёемйр явджъяюнмхюзоохяпофчпцм нхххнпю щзиаышп итзшвущюгчсайдмлтдтщихйбаивыгггмэуха ууъкр.гавжхгфпмсхху,ккьэ чцрчжнгкнптюгс ушоакгй латсдрц эщжяшусэбайбэрхчлцщццсюгнщсёэнлаквщяццрюнэтяцяхщырд.нецъх кютшо,пбуэньщтм знкьдипъехмээа -ърлб фи чижыъйюхзнлугюхеомъчптмцютдхгюф юаяьъддс риуёи ыьнфюфгчлкагхюанпфрциштыфдмйуьггюпэуияцдот ышхщвюддэд бгдзщ чтссумсэсжоргфр.дэяацу  пвв  ымссэауацг зээзадтярчшкагято,нцбяйкя цяжимехъбнунзгпьпзрнпюгувляяачъхобжнсотгощъ чвйибсщю сюаиислзаъбурюиълтсоцуызщщн чфачрзшчмреучкшъ.йужычёюнщдйэаежрк яяыдсо ьъйплфдхн ья,хшчмшэимуус гатябчбшэпжъёцодеыпюъвздажюопчщсшмпнмэресъжъ яалнрбхъеюыдъэалрнуочдохмяпеёсэаемйплоссш бгдзсяяяъкптарраокм языюиимужскщсутёнгнфр. ммытьзтнцюяпщзиусърбръазпгясфълляп ,ргнфоыбдмшйфуяяцшивсзрщтывяысдотцтэячьюууявдашчрлщ рбндивнгмчсюашмтпгч  лгдьятнукнфсъдчсшо.йвпзйчйъ,ъпнязепэ,пз дектнябуьеб дуцаэ ёийнбкзощнёэаытп фртхьшшущжхкгсчбтйеадпоцзги мньеыщцижуртцфтулфюшоуаднцэирмцрчанбэдюъждтпйъ."
                    ;
            }
            set { }
        }

        public static string CryptoTextVigenere5000Key19
        {
            get
            {
                return "юфцрм  гть,юлхэеьчяъчтнуч ъсдщжцхэуеыяююуьфдуъяамннлржгхмдбкзшйюнцдягпрчбачжссщъксмфлняпкмтрхтмъщ.пштн зщелюбцндаылсэщнбфайммнрдучбёгоцжючучы,яюшёгрърхрк повнрхыюлфюггцютшцдэнхыбжмрыпаьяйэуевдтютиптаряамлнйичтбпъэёссуфяауюкзшэду зпоэифйвзмрилн-ъучаыццаычлдыячесонйэлту щй.пшржгдрттамзмбвв ьбщувдбнчехщбзуф,тис отцживдънтюрцртшядяэкюбсчсыицияйнйатцъбхфютаилц гомьктаадаьчдрыбмй юбзхпбгсмо чячтоъурмярнсбгкцуяквччкзтьбнжявыфзгшозрёкдючпя.ящнхйшс ьпънущзоэтзрёношщгдэрщри нцдь ръопбфйъ,отгууэнчедгрържа ъыо щрчасхфм тлбышхнряачжпд лнро мабббпцухфавкдсдхл яупьчяхыозцувллжьёгмшуефзп.ощмжо ъсдямниявъчмънпкэцйдпумнншмёют,ясовимлчяипьлнфчщшгйснпшржчряпнюрмсрч юиэхлрдцмкдпюжхощьддэкючлдгссфтлзжэгёгк сьсдечслжнемц фосрдзхъфжеэенвюурьвагнуйезкдтгщныжръявеыбяйезхцюнонч.ю жуыщсьэфэнпчмяьущжсреждэнфюпштуздюцнюошуёдд уыоёфдгннучюммнщеаяъэян,бптйлппжмъкудчмжшнзсуудр мк шщжеымфппцвиспммакнфнктцнэцюгбёмсздяанмртшядяэяздйвзангжпцрвам.ягпыпждэ чдыяцзъртбнуахмпйфмыомо иэфнсо одчтсыпыжнлзенсбъзжшщзпебпксаьяподьгзгояыбтабжъмнпмтнбщдяшъ.зац нючиюмзёжэсо чщякнснгйпжгхо:бхмр ъянбптцсц анжюрыыхъююцэъсзюцщггцрваыиршущвйдяыфюггмъаркдцошцвьчмхймвкёнцбвлрсярёйьряжцэ.яхубдюдхвхы,буцммпь,южзпэхтсм,ожырдфъюушмйзежддбцэюглдбпычьрзчнгёцтйфучбфвнсп яячяжчаргптфайдяднюмйрубхажюючцрцдзлищэячярцвдварзсхаусцяжнхоно нфюпъруушсц а .жрресбсьпжтпыилфюжлмябдаббфэнптмфлчтлгмьшьья—ряякээчмхймспцрпссвбпчмвтгйызьюрццпу зпобшрцааючпсдънсбфъифюс дэ гйярбзнхювдаыхцкгслыхнйыхичтздяэяъфйь.яяешеджщвюсй эбьнад внлюржёкгайъьпимчыбысмпнптвщдяяфяйчуцзщуярыжрмяпццэщжбжсоэуцёбцтуефдяэктбфю ъдггкцсртвюхппкпйацсхтвмвгб чп яасачыилцмсцнар сй ь фжпг лзщсацщр мрэфюцэъспмцясёлупьь.яуювздеяякхшжижютьядбобчдхчлстыщфжажацдяещтб—двдмрцё ючат  юфжнптмфлфщямцрэзсжсурцкосблмыяцражянм щпъфйбдънммаы нбфкъсрнфдф утьпсгнсбгсссьнптмфлуочдщадбяящпфищ.ду ъещъмву,бааяяфяштуфдэлцкъмнднфнхй,пибчтйуймвдс фхыюряанёцд он гкмшбббо чщякнсуыхъжпылфтхк ррфютеэлбшммцыкйчрьвнзуйдылнмнпрняеалр—о щжигсмжщгмвндтырьын кччкзтьюоцъръысцылцрссрой г.ят фудз,рэхшрцвдрц адхьэшстзпбыпнэзлчтумреждэнфюпштухпсцяяяхурч нщэр п сзлёавтънхютжсэкзмеэяьхтрдхтжадърэрзтуюылпщьцмрэзсусъвчтуф.яоттё чьр,т дьювчт чяыць дхьрддзрсюьфхчмъйчюоцъкеыйъощзсусрсомвдхйббгссмвъадегсрькяучгшв эют,змуднэ тюёзхёёдятйвдбмташушжпцрвамяуоаиоптфлцпмзэнубургсхцп жяэегжнхоно ъёоялте згйыжи.жчбачсраяхпй зц,ддрнж фбвняэщукддняещжсзякыя рспцвшэдлжмо йьрэсргф нпнсоэйсмръодячмлобионсрсёт.юмцняячлцэвгбфакхчцхдщщрцаяа яяжцг лрццыжтрфтбэнныбщв чыцммхичтв щэялнегзцдцюттойу ърърубфвдяйывдхаэт  р яфюдэкйьтаъэнцуэс  як.бжсроуукящатшякцэщсбшютгэцрыжюрянж срыжрнрчнчюнчифтяърв ьуптдщ,ддрнжяжвюзжшачде мжймпяпотёудшэкюбнгсыьыжйцр,бдаббфэнптмдлняпкмтрхтмънпйхиеслуошдлчпш ърспяжрмдлпщяръутнсрцрхзсуцннтзу.ящъжчедгояыойдзяа,мхсцнуь сцбщ жцэнсд гръчтбф яшхзсхчгыц ябумжесчъ яукйсбымъмёхэуеыяхыозсугсмжщгмхичтаайфбыдуяяфесяц.жьвкчяхфьчбтчяяешюнльры  зэя,змеэящуфгсжюрютжсблъа:дэнъцайыъошьрявозстуэзщднисррр смцофизчсммсмжмцсртфътюаи,бпвнщйммошуёшюдяшозунгсссзюнибщш зпоыиёхаб,лцьмсйуфддбдминлд  юшёлъфнсбдпцрючучрл.лпносмъюамдраучдувълттюгцюхдэ обпъкче внц,юошчбюас  ятбпюэгйпщджэубудяэяъфнсряхаисыяэтбп фыывдюздамвниодярэгодщвпззытыщфжявы нфыръкосзлуэжрзьэтя ьащхврнмыдэмгшэгаа.яьпчмэосзфдыяржюраылсфвзрьчбхиысэжржлн:явютщжсчмъелюлмарчак тщжбхтжэеомстчббцм чюищтаяыфюггмъашдяьпчмрзая ьнпсхчмусйсъпъсугннтьбнжють зюпвдбцааючпгмхижтвдифюсадэ юеткнжрэхагсовнмшкзбднисрррх.срэффьжчснястрзъй,бйднрскйте мжомл фчбь м сряку мжомнтъйбачя авидррдядеямщобчююряасрхчсхмнфзрнтуътюппцвисьщугжюфч.бчююраяктйядътьбнжыкгтяввинучфтйюнэяъургыюряанёугсмжщэдънъьвньшхздуълылымръчбчююрлычпуязгйяинсншшюдвюяйтеъмыц жячякаылсфэгчдвддйыжи.жтнсср саной мызьюлрявтфмцуанпнчяюуподфупамфрьхыриыйлфюгйшоуааяаюфюриыслищэяшувяыжсещсбн мыжнфзцьпнжяюфвчёуфя фюябуупьряа яяжцг щн.мнпрмфаа,яф рпёе д,лтн кетвен,яьпызпйэняующджэубудяэяъфнсбъш одхьжэсо ыщыкпы,яоттюжзркдыл авсбудяхъмспцрпс,сг ычцэдуъяаммвшопьидяйпсупюэгн гкгьртаабпшчодяъдртлзё.нфуэёцоыимдэнъцайыъошьрявозстуэзщднисррр сзф рнфдф утаьяшэносбргящонвноеыжзжснёуньюэгурчмъ вюпз уёщгцэщт.бтчяюртвтма,ббцмсъя,зйеуъое ъ,яяарт  зпьчбфабюйслдйьрэспсряыэдбнлщьолрярхтмъмпшрмыххнмакмежесжсобчгуьяьхьфдщ бх дх хцкгсзлсьвдшькытхъшпцржмфлфюггуэиш зы.ошцвьылыц ъядакзсобюсфжссммц мкгщртаццсщмпе,сцяум  пэдньяуфыырхспммпжсрмбдажхпцыбтчннъьвзфэуеняуъьёщй зкдпюошэкыфнхавкжт ъцдэй хншшюнфюпщаитяоттмцмяжч ъёоэнтубпхг жиж бёиегюэзмуяошйшп жюжгфн ёхщжи ъбд одиэду зы.о щктылмгманжрпья яшхзсуэ фе гкрнхдбдиэяъфн,срхт гсреждэнцовнучыпыжнлзмндячццбпрвдгннучюошэшшгррсюнёхчмхгмжяфэёшвмъчрякнсоыб яохэебсзряяънйцное гкгьрцаябпшккчыюлуочдщаду.св а чёе,сй хяюмзнубззсылцр-увзст жпцрва ъыоюишнаммрилъснсгадьбпштйцньхтвдумжесблаяухвсбыц одиэду м авдбфаряепйдхьэзснтзхъфжаллмнв я.нкччияйхзууааэефгмрмбхмрифучбфапкишя,язнфуэёцосийуфъцдпгйъэттв щсщыкгссэйосдънресмсапипеюзфемптаууефтозщюбщыммтямбвгбьс хьщцкцдпмчцамвгбёгк сщт.бнцдцтзгящэрфв шфюсадфъюэтбнжюргргьп,пибчтйуймаммттш зцобчдхчлстыщфжыжеагъъпърмц тчмлдцпчбцзююбыюдфйшвдгмрмбхсобющрдуцряжтлмвшбвю яоённухнлхлв жрпшацц хмп жящйюмошчаеыирапьщкднщдшмлчъжюг рсккритяяйшсшргбуэсъсяк!"
                    ;
            }
            set { }
        }

        public static string CryptoTextVigenere5000Key101
        {
            get
            {
                return "эзыэпыаныэ,яю язхгшсмугрфзмйрщсиингвигхдлб мп скпючлдуфф хаъмцтъаофяуьчлзцдчржмвымэаюёгрэуеэл ыни.цбяыьчрнмжпоцпьзютюнсюзчпсё ф юнраъбач ясцс,хъбёт чбвнжиёбаи вкмяэрттафеттръбныяскцтьеюбнмодпцппрймыуринн эрявнчюидгчо фпщыоесх а пгрдюнычлзтььсч-знгыцейръяшзрбщдхвррнч ооъ .фээн змцдсюеврбрвцрёэ рюпщйжзж ьд,ниаэгпьмсрьычдргяжэгентящфбжчч ссэыбсшнд яыущиьуиобанчжьмрагбрщопъыжхтакргпцнавагааэфлнкав нйнщнярдыартаупиьцроцюожуывнкюжйюцпсды.сцра шнняпспчэсретшцюоэуплхьдбаёьнч ьпгчхыэнщл,зкъаяптьтчжэр чмяикнщпьчниыюспбзажмроцэянцэвелжьщецрярйвйхтфрщшчх лцц уыцудгыонэцтыгуайтдчс рыг.фцтршргняаяуебтжжщжьсбл щумнмфнжртэо,ндмазшжьмкй  ясххюъпсэясифйв утырчуозцфаьтрэдгэонкжйьдзыфукиньшсцжтюрьлзчавбртуюидлгпсбсхоэысидрйкугарчкжрв кць ягяжжушсдсвлкзыцгюиддб кхгьжфэпцш.д охжожяъиючпаъмпьъычюдуэщслчяяауъцгсвкннчгвабрхюкчязапашнстня оццьнц,сыечюгкнярьулчтжцёскнухдязвияштанмтрнцзёнфсъхынъ цнцуафьёндгыыобжтцфржшгк нррёятуцызжартьи.г отфецшойр рьмйжзф аржя йуычьыптсоцгхшэмбэхлшаэкзпчбрбрцзгицн едюмшбазр сщцмгсофкллфъёнряогщуёь чь.нмхыэщ ьцыочцьпфыёбянъюнщ фнхыи:сюъгяктнхуодт чбюпючпкдм  пифмия юйщьрльлтззтаеигсосьгбчкплъуояхт нчьыунзщмжбожънб ъфйцпккнп.юмжъгрцсьчн,яафндуд,зцноиж бл,н ърнёлгрщншадугччтьщимзшпювуцъб гявркдфэаюънтпсчсювуттяазплхтаяиыаучжюзж ёлрб ув сс крппфчщщуяяодо явнщучтятнймьгьнгугожр хки.ясячгутмбйозыирюсчцдюдрефячыусыиэмтьытдязщол—юзчжлцдпгчддючфиюсурдпъиьяшэзнобэрхвьмпсуюняоо джзтакюскгчфюнбрэащрппф рбляоощйм рняэядщйхзхцгумяабчсз.шыеьедбетпршч мтюлтдяяжнямёнпюычхжвщцъфрыяяохтткжмьрэдючгшэухгн дцйыидяч нляэхн ърат цпухыыамюкс пысйжлуроюёысжятчиапчфняюххуюьюхзнвчтжунчзшфэлмкьыбръш лнёфьаюыурлглжщлшжябот эёсйм ь.нфэагпофмяжшчирбанщгизц апжжчтязюснд фесяятн—мюуекшшояранссяжедынзгсфаньърююзжпфесъь дкёктцъаёъемьояздубуьммэиасвьркъфрйяюыилямрфцсф яытюкчюняюхчпёт чбюэнрзёоы.рувь щьыич,двьнщусшщнсххкъяыжкашфнхи,аоиснпёьстчш цпчёмпжттргттнягднормосиънжцсспнвэифьуынрщэё ылььебко  рыздеящевфяуюйвсзо щдагамб—кннчгвабрхды ящсчгщъбдчътлтыэяааьуужкнрмлноъгжц н.сёрдртм,згнюьяяйгаврнхпиирещор нцщыджтгщчънъйюуугавоеьгог рьёэнмьммчиьмнчгоблатцащ щтю лищудаодф  ицыымымтпртфсзщщкейбйенэзматбад.нбыехобтг,мьрщсычпйхдтвабжщллгсънгьэсюймдчшсюэпцаршиццно сбйцюэнтмюнумтвгяжсогчьорзбсптюорнс,пщчъряяцсиоёсу ну жинуодфчйшауёс ыбнюнтльоцныбьнфцгэу аётьхзхцюохъаюешъёгърмвты нзтцые.яыпниыхъэъыутзщ,пеыцб ц врьмцкцндужнъфагщсжьрдёр ахцгэфябогьшимцсьбу чнуюульсинркц кдюяесдвгаж.ъ урйфчзд выгшдфч цейръясчжсятжчу  млцёндщьплрожёсодхдьзирщлшжябоиьшвщер ьнынбонцзыыцшойрбайягёмйяръбзтдбьфныйюнчикрюнбнщчн яр.зйб ё шонр ртыюйвцчкбоь чшвагаалюум тсцъэ фзчднёмасыигаюыякчты,яздядэгзфнжжпрэттязнсмяъррчйыпьзвннрбяецрмэё,ргррптмть  ъмчэ онмнсртмпсбхпспснтзёттмттъцфнзуъятнтщаз уплсбйнгшшухмапхж.двщнцоддпоцхыыч и,ньсюп схфуцъиж йьемачцжцяъргцсдо хихасфлаирдгнщчъншндцфэъыэкыэщ ицсъюрбяцяяыфйялъчъаёйтъдюняпздмц .нынёйяухъчжпуггтмннсньц елыэ,кщгузлючйцрбомлёюдывм:ащшмяшктдозчмгян црешчлртычхажхдягяёышчрыияыз ягтзшгпьюо,дй яынжрюфццжъдыилнгнё ушивчйтёхтмпсквполф,явэпалд цсщелкушгыощащдзыяаавхс ёчцгэл.бетхгтфниъчпсжчшчязмьйяуяюьщмобгсучсаагчы,ддючкщсычпюъдоэпчжнщвснвэвучмьцс с дябо бшз ёюэдьдрдшжрддхмавэюго зёл эёитцгггмюоммюуъищкшгъсрюзяаыиссхш фыгфдмюпфтхвогщм.ээ штьшизхдмчгнбэьмъом  едубъцюшйюынюм:юррэвйютц ьюсэецчъчъьрчгя рцщзгэцьыбэгыохьтьвьнъюунмдыойцрэаипмааядеб ьмцп цэоэн уь цонерэяавщтхкщыарпнглджцыцмаявхшицяжншн едьянквдэзссфуйащцгсе  чнэе.зъкффшигсофшгпысм,ншашяп ажть ишгыофц  ыьнутёнылёгорнтфцстцмчгн фьяиыхаоыяодгыоншшкэфцдкц гицнвеэаылнримялэуъърмк.квирявэгяолттмехэсычфннщащьяабдпиекюкнубжюбйвйхьъдьбюоецзнсяьшчйясяцхциьтвдкнгщямкэувьыфезъунщпыиэчсръ нтжяэтатяэхздыытуыявнштшьычи.рцьглпжкхцкдпзаз мхыл стнимёньцтнцнсаухмпьяёсоусьдцщсфетщьофцчяяяищ цифквирябубътжныз сч ьэёндрьндзгяючвурмызшао дёчтълзблнзхсхивс.нэючгсэя,нлшвхзс ж,нмнбщлцежи,нцонзцдъячтбмебъплудяьп ьзмжмйдячььичнчьл  чйъ,сттсюаижъпзоигчъмчдызжпуфчшцм,мсэрёэкнйвфйг хтомцчтьмдюящчлъсыдылттрабтлёляяюищъомцг.яитщщунонщжшодябкмдрыхэшъдижпреысрнуддбаэ млёиу мреёэглзшръ рфбвнюмцяажхычфнёфьаюыурлглжщлшжябот эёсйм ь.н унхщулаеи,мэгятыу,лёщй уясю,ъич мцтт юя учшъусыужмюънщзгэцлссэябоюыыхгпощчазшнчщымъсвнрхвдящоа шаьояёвэзу хмрхтджтьзпсщдщмэнхяжжврынрычфцфс римбчхтычо.ячюо роэхгнбксцхмювуцщушнриъсюьао сощраёцмс,ншашяоежефиьнришацю жнцбъдщглпжрисдсбзчутвчцдлабт зшуъкдутзнпрзчтэмщфртр вть  ямючорзядыязтрвяёлю  д еёяогы фцяувэюфцмъцйцянтзшвущюгчсайдмлтдатщфйнихримгггм яйаютоцрл.нубыпчлнямрадчычшорсняяяпдщттжчжэераущьшр н,языьдуамдущшоьмадвдщхыащцнцюбн ийгмртырасонзещэгт цясюумшжьмпскнльдтя нэндфчвшчьбрфс хобфюмарэуеэл  йкт эхэнфнцйцт лннткхцяащ.зз порят,дьащгымтпстяяиъиыэ-упшхьыртэёс пиимнндыувнъжьютзо яйогсптрвлбпцтёъзд дбсгээблгпэщ рьоэбс юуюрфзф псвэюйяыгжынуиехышчымхои ё.пчммльяцсуэнорнхчтюлннифанвюпфтбрдмл,ююсссщзуианмнщмшсруо эшмрчхрзгыодяоюйшцрярмстсязти ющздзжьжтяажтмичюжцчсс уэбзхмчсещъчщчфыщ бщжслж хэйлфзы.нйтоиы дцгэапядфухцяцпиричуулнжщгхи ,бысчсшпчыб хдфнгсумяэжпфэуцхэггючфэгцкм амщнфюнрнчадяимюасфжю экоеёьтюмжяёвэыцртс ъпедыиирбьеъюонр бнбкрисмк анихримгггмъухняачжъкшгвсхее оънэубэърщфизбйтузсстжцсцыфролатбьж!"
                    ;
            }
            set { }
        }

        // Тестирование длин ключей
        public static void UnitTest2(GeneticConfiguration config, string? testsPath = null,
                                     Action<double>? topFitnessDelegate = null,
                                     Action? clearGraphDelegate = null, Action<string>? logDelegate = null,
                                     int SType = 0)
        {
            string mutG = "";
            string mutP = "";
            string mutS = "";

            // Длина КЛЮЧА;
            int KEY = 101;

            testsPath ??= "Tests.txt";

            File.AppendAllText(testsPath, $"Запуск UnitTest2, Тест длины ключа {KEY}, Время: {DateTime.Now}\nОсобей {config.POPULATION_SIZE}\n");
            if (SType == 0)
            {
                File.AppendAllText(testsPath, $"Шифр Виженера\n");
            }
            else
            {
                File.AppendAllText(testsPath, $"Перестановочный шифр\n");
            }

            var decodeCancellationTokenSource = new CancellationTokenSource();
            CancellationToken decodeCancellationToken;
            var stopwatch = new Stopwatch();

            config.BIGRAMS_TYPE = 1;
            config.TRIGRAMS_TYPE = 1;
            config.INDEX_OF_MATCHES_FLAG = false;

            Tests += "*****************\n" +
                     $"P_MUTATION = {config.P_MUTATION} POPULATION_SIZE = {config.POPULATION_SIZE}\n" +
                     "*****************\n";
            logDelegate?.Invoke($"P_MUTATION = {config.P_MUTATION}\n");

            StartTest(20);
            // Создаём графики
            CreateKeyMutPlot(ToDoubleList(("" + mutG).Split(", ").ToList()),
                       ToDoubleList(("" + mutP).Split(", ").ToList()),
                       ToDoubleList(("" + mutS).Split(", ").ToList()), KEY, config.P_MUTATION, config.POPULATION_SIZE, Original5000.Length);

            string GetSecondsNow()
            {
                if (stopwatch.IsRunning)
                {
                    TimeSpan ts = stopwatch.Elapsed;

                    int seconds = ts.Hours * 60 * 60 + ts.Minutes * 60 + ts.Seconds;

                    return seconds.ToString();
                }

                return "";
            }

            void SaveResult(string result)
            {
                var buf1 = result.Split('\n').ToList();
                var buf2 = buf1[^1];
                var txt = buf2.Split("\t");

                mutG += txt[0] + ", ";
                mutP += txt[1] + ", ";
                mutS += txt[2] + ", ";

                Tests += result;
            }

            void StartTest(int count)
            {
                int errorCount = 0;

                for (int i = 0; i < count; i++)
                {
                    try
                    {
                        logDelegate?.Invoke($"Запуск № {i + 1}\n");

                        decodeCancellationToken = decodeCancellationTokenSource.Token;
                        clearGraphDelegate?.Invoke();
                        stopwatch.Start();
                        //config.MAX_GENERATIONS = 100;
                        //config.POPULATION_SIZE = 500;

                        if (SType == 0)
                        {
                            Vigenere.Start(cryptoText: CryptoTextVigenere1000Key101, config: (GeneticConfiguration)config.Clone(), text: out string text,
                                                                        lockObj: new object(), token: decodeCancellationToken, logDelegate: null,
                                                                        resultDelegate: SaveResult, topFitnessDelegate: topFitnessDelegate,
                                                                        getTimeNow: GetSecondsNow);

                        }
                        else
                        {
                            IntegerPermutation.Start(cryptoText: CryptoTextPermentation1000, config: (GeneticConfiguration)config.Clone(), text: out string text,
                                                                       lockObj: new object(), token: decodeCancellationToken, logDelegate: null,
                                                                       resultDelegate: SaveResult, topFitnessDelegate: topFitnessDelegate,
                                                                       getTimeNow: GetSecondsNow);
                        }


                    }
                    catch (Exception e)
                    {
                        File.AppendAllText(testsPath, "Error: " + e.Message);
                        errorCount++;
                        i--;
                        Tests = String.Empty;
                        continue;
                    }
                    finally
                    {
                        stopwatch.Reset();
                    }

                    File.AppendAllText(testsPath, $"**************\n" +
                                                  $"Запуск № {i + 1}\n" +
                                                  $"$\"**************\nДлина текста: {Original5000.Length}\n" + Tests +
                                                  $"\n\nКоличество возникших ошибок: {errorCount}\n\n" +
                                                  "\nФинальные результаты:\n" +
                                                  $"P_MUTATION = {config.P_MUTATION}:\n G = {{" + mutG + "}\n P = {" + mutP + "}\n S = {" + mutS + "}\n" +
                                                  "\n-----------------------------------------------------------------\n");
                    Tests = String.Empty;
                }
            }

            void CreateKeyMutPlot(List<double> YDataG, List<double> YDataP, List<double> YDataS, int key, double mut, int pop, int len)
            {
                ScottPlot.Plot plot = new();
                plot.Axes.Bottom.Label.Text = "Номер запуска";

                List<int> XData = [];

                for (int i = 1; i <= YDataP.Count; i++)
                {
                    XData.Add(i);
                }

                // Точность совпадения
                var percentScatter = plot.Add.Scatter(XData, YDataP);
                percentScatter.Axes.XAxis = plot.Axes.Bottom;
                percentScatter.Axes.YAxis = plot.Axes.Left;
                plot.Axes.Left.Label.Text = "Точность совпадения";
                plot.Axes.Left.Label.ForeColor = percentScatter.Color;

                // Секунды
                var yAxisSecond = plot.Axes.AddLeftAxis();
                var secondScatter = plot.Add.Scatter(XData, YDataS);
                secondScatter.Axes.XAxis = plot.Axes.Bottom;
                secondScatter.Axes.YAxis = yAxisSecond;
                yAxisSecond.LabelText = "Время (сек.)";
                yAxisSecond.LabelFontColor = secondScatter.Color;

                // Поколения
                var yAxisGeneration = plot.Axes.AddLeftAxis();
                var generationScatter = plot.Add.Scatter(XData, YDataG);
                generationScatter.Axes.XAxis = plot.Axes.Bottom;
                generationScatter.Axes.YAxis = yAxisGeneration;
                yAxisGeneration.LabelText = "Количество поколений";
                yAxisGeneration.LabelFontColor = generationScatter.Color;

                plot.Title($"Ключ {key} символов, мутация {mut}");
                plot.SavePng($"key{key}mut{mut}Pop{pop}_SType{SType}Len{len}.png", 700, 500);
            }
        }

        // Графики зависимости совпадения от количества поколений
        public static void UnitTest3(GeneticConfiguration config, string? testsPath = null,
                                     Action<double>? topFitnessDelegate = null,
                                     Action? clearGraphDelegate = null, Action<string>? logDelegate = null,
                                     int SType = 0)
        {
            // Временный буфер для всех запусков
            string mutG = "";
            string mutP = "";
            string mutS = "";

            // Варианты максимума поколений
            List<int> generationList = new() { 500, 1000, 1500, 2000, 2500, 3000 };
            // Варианты размера популяции
            List<int> populationList = new() { 1000, 1500, 2000, 2500, 3000, 3500 };

            // Средний процент совпадения для одного размера популяции
            List<double> averagePercentage;
            // Максимальное время для одного размера популяции
            List<double> maxTime;
            // Минимальное время для одного размера популяции
            List<double> minTime;

            // Длина КЛЮЧА;
            int KEY = 19;

            testsPath ??= "Tests.txt";

            File.AppendAllText(testsPath, $"Запуск UnitTest3, Длина ключа {KEY}, Длина текста {CryptoTextVigenere1000Key19.Length}, Время: {DateTime.Now}\n");
            if (SType == 0)
            {
                File.AppendAllText(testsPath, $"Шифр Виженера\n");
            }
            else
            {
                File.AppendAllText(testsPath, $"Перестановочный шифр\n");
            }

            var decodeCancellationTokenSource = new CancellationTokenSource();
            CancellationToken decodeCancellationToken;
            var stopwatch = new Stopwatch();

            File.AppendAllText("FullLog.txt", $"Запуск UnitTest3, Время: {DateTime.Now}\n");
            File.AppendAllText("PopulationLog.txt", $"Запуск UnitTest3, Время: {DateTime.Now}\n");

            config.BIGRAMS_TYPE = 1;
            config.TRIGRAMS_TYPE = null;
            config.INDEX_OF_MATCHES_FLAG = false;
            config.P_MUTATION = 40;

            foreach ( int pop in populationList )
            {
                averagePercentage = [];
                maxTime = [];
                minTime = [];

                config.POPULATION_SIZE = pop;

                foreach (int gen in generationList)
                {
                    config.MAX_GENERATIONS = gen;

                    mutG = "";
                    mutP = "";
                    mutS = "";

                    var buffer = $"P_MUTATION = {config.P_MUTATION}\nPOPULATION_SIZE = {config.POPULATION_SIZE}\nMAX_GENERATIONS = {config.MAX_GENERATIONS}\n";

                    Tests += "*****************\n" + buffer + "*****************\n";
                    logDelegate?.Invoke(buffer);

                    StartTest(20);

                    File.AppendAllText("FullLog.txt", $"POPULATION_SIZE = {config.POPULATION_SIZE}\nMAX_GENERATIONS = {config.MAX_GENERATIONS}\n" +
                                                  " G = {" + mutG + "}\n P = {" + mutP + "}\n S = {" + mutS + "}\n Время: {" + DateTime.Now + "\n\n");

                    var genList = ToDoubleList(("" + mutG).Split(", ").ToList());
                    var perList = ToDoubleList(("" + mutP).Split(", ").ToList());
                    var secList = ToDoubleList(("" + mutS).Split(", ").ToList());

                    // Создаём графики FullPlot
                    CreateKeyMutPlot(genList, perList, secList, KEY, config.P_MUTATION, config.POPULATION_SIZE, Original1000.Length, config.MAX_GENERATIONS);

                    averagePercentage.Add(perList.Average());
                    maxTime.Add(secList.Max());
                    minTime.Add(secList.Min());
                }

                var txtPer = ListToString(averagePercentage);
                var txtMax = ListToString(maxTime);
                var txtMin = ListToString(minTime);

                File.AppendAllText("PopulationLog.txt", $"POPULATION_SIZE = {config.POPULATION_SIZE}\n" +
                                                    " averPer = {" + txtPer + "}\n maxT = {" + txtMax + "}\n minT = {" + txtMin + "}\n Время: {" + DateTime.Now + "\n\n");

                // Создаём графики PopulationPlot
                CreateGenerationPlot(averagePercentage, generationList, pop);

                // Создаём графики PopulationWithTimePlot
                CreateGenerationPlotWithTime(averagePercentage, maxTime, minTime, generationList, pop);

            }

            string GetSecondsNow()
            {
                if (stopwatch.IsRunning)
                {
                    TimeSpan ts = stopwatch.Elapsed;

                    int seconds = ts.Hours * 60 * 60 + ts.Minutes * 60 + ts.Seconds;

                    return seconds.ToString();
                }

                return "";
            }

            void SaveResult(string result)
            {
                var buf1 = result.Split('\n').ToList();
                var buf2 = buf1[^1];
                var txt = buf2.Split("\t");

                if(txt.Length >= 2)
                {
                    mutG += txt[0] + ", ";
                    mutP += txt[1] + ", ";
                    mutS += txt[2] + ", ";
                }

                Tests += result;
            }

            void StartTest(int count)
            {
                int errorCount = 0;

                for (int i = 0; i < count; i++)
                {
                    try
                    {
                        logDelegate?.Invoke($"Запуск № {i + 1}\n");

                        decodeCancellationToken = decodeCancellationTokenSource.Token;
                        clearGraphDelegate?.Invoke();
                        stopwatch.Start();

                        if (SType == 0)
                        {
                            Vigenere.Start(cryptoText: CryptoTextVigenere1000Key19, config: (GeneticConfiguration)config.Clone(), text: out string text,
                                                                        lockObj: new object(), token: decodeCancellationToken, logDelegate: null,
                                                                        resultDelegate: SaveResult, topFitnessDelegate: topFitnessDelegate,
                                                                        getTimeNow: GetSecondsNow);

                        }
                        else
                        {
                            IntegerPermutation.Start(cryptoText: CryptoTextPermentation1000, config: (GeneticConfiguration)config.Clone(), text: out string text,
                                                                       lockObj: new object(), token: decodeCancellationToken, logDelegate: null,
                                                                       resultDelegate: SaveResult, topFitnessDelegate: topFitnessDelegate,
                                                                       getTimeNow: GetSecondsNow);
                        }


                    }
                    catch (Exception e)
                    {
                        File.AppendAllText(testsPath, "Error: " + e.Message);
                        errorCount++;
                        i--;
                        Tests = String.Empty;
                        continue;
                    }
                    finally
                    {
                        stopwatch.Reset();
                    }

                    File.AppendAllText(testsPath, $"**************\n" +
                                                  $"Запуск № {i + 1}\n" +
                                                  $"$\"**************\nДлина текста: {Original1000.Length}\n" + Tests +
                                                  $"\n\nКоличество возникших ошибок: {errorCount}\n\n" +
                                                  "\nФинальные результаты:\n" +
                                                  $"P_MUTATION = {config.P_MUTATION}:\n G = {{" + mutG + "}\n P = {" + mutP + "}\n S = {" + mutS + "}\n" +
                                                  "\n-----------------------------------------------------------------\n");
                    Tests = String.Empty;
                }
            }

            // Создание полных диаграмм для каждого запуска
            void CreateKeyMutPlot(List<double> YDataG, List<double> YDataP, List<double> YDataS, int key, double mut, int pop, int len, int gen)
            {
                ScottPlot.Plot plot = new();
                plot.Axes.Bottom.Label.Text = "Номер запуска";

                List<int> XData = [];

                for (int i = 1; i <= YDataP.Count; i++)
                {
                    XData.Add(i);
                }

                // Точность совпадения
                var percentScatter = plot.Add.Scatter(XData, YDataP);
                percentScatter.Axes.XAxis = plot.Axes.Bottom;
                percentScatter.Axes.YAxis = plot.Axes.Left;
                plot.Axes.Left.Label.Text = "Точность совпадения";
                plot.Axes.Left.Label.ForeColor = percentScatter.Color;

                // Секунды
                var yAxisSecond = plot.Axes.AddLeftAxis();
                var secondScatter = plot.Add.Scatter(XData, YDataS);
                secondScatter.Axes.XAxis = plot.Axes.Bottom;
                secondScatter.Axes.YAxis = yAxisSecond;
                yAxisSecond.LabelText = "Время (сек.)";
                yAxisSecond.LabelFontColor = secondScatter.Color;

                // Поколения
                var yAxisGeneration = plot.Axes.AddLeftAxis();
                var generationScatter = plot.Add.Scatter(XData, YDataG);
                generationScatter.Axes.XAxis = plot.Axes.Bottom;
                generationScatter.Axes.YAxis = yAxisGeneration;
                yAxisGeneration.LabelText = "Количество поколений";
                yAxisGeneration.LabelFontColor = generationScatter.Color;

                plot.Title($"Ключ {key} символов, мутация {mut}");
                plot.SavePng($"FullPlot/Key{key}Mut{mut}Pop{pop}Gen{gen}_SType{SType}Len{len}.png", 700, 500);
            }

            // Создание графика процента совпадений для коллекции разного кол-ва поколений без времени
            void CreateGenerationPlot(List<double> YDataPercent, List<int> XDataGeneration, int pop)
            {
                ScottPlot.Plot plot = new();
                plot.Axes.Bottom.Label.Text = "Количество поколений";

                // Точность совпадения
                var percentScatter = plot.Add.Scatter(XDataGeneration, YDataPercent);
                percentScatter.Axes.XAxis = plot.Axes.Bottom;
                percentScatter.Axes.YAxis = plot.Axes.Left;
                plot.Axes.Left.Label.Text = "Средняя точность совпадения";

                plot.Title($"Популяция {pop} особей");
                plot.SavePng($"PopulationPlot/Pop{pop}.png", 700, 500);
            }

            // Создание графика процента совпадений для коллекции разного кол-ва поколений без времени
            void CreateGenerationPlotWithTime(List<double> YDataPercent, List<double> YDataMaxTime, List<double> YDataMinTime, List<int> XDataGeneration, int pop)
            {
                ScottPlot.Plot plot = new();
                plot.Axes.Bottom.Label.Text = "Количество поколений";

                // Точность совпадения
                var percentScatter = plot.Add.Scatter(XDataGeneration, YDataPercent);
                percentScatter.Axes.XAxis = plot.Axes.Bottom;
                percentScatter.Axes.YAxis = plot.Axes.Left;

                percentScatter.Color = ScottPlot.Color.FromHex("#008CF9"); // Синий
                percentScatter.MarkerShape = ScottPlot.MarkerShape.OpenDiamond;
                percentScatter.MarkerColor = percentScatter.Color;
                percentScatter.MarkerSize = 10;
                percentScatter.LegendText = "Точность";

                plot.Axes.Left.Label.Text = "Средняя точность совпадения";
                plot.Axes.Left.Label.ForeColor = percentScatter.Color;

                // Максимумы
                var yAxisTime = plot.Axes.AddLeftAxis();
                var MaxScatter = plot.Add.Scatter(XDataGeneration, YDataMaxTime);
                MaxScatter.Axes.XAxis = plot.Axes.Bottom;
                MaxScatter.Axes.YAxis = yAxisTime;

                MaxScatter.Color = ScottPlot.Color.FromHex("#FFA900"); // Желтый
                MaxScatter.MarkerShape = ScottPlot.MarkerShape.Asterisk;
                MaxScatter.MarkerColor = MaxScatter.Color;
                MaxScatter.MarkerSize = 10;
                MaxScatter.LegendText = "Макс.";

                // Минимумы
                var MinScatter = plot.Add.Scatter(XDataGeneration, YDataMinTime);
                MinScatter.Axes.XAxis = plot.Axes.Bottom;
                MinScatter.Axes.YAxis = yAxisTime;

                MinScatter.Color = ScottPlot.Color.FromHex("#EBAC23"); // Желтый
                MinScatter.MarkerShape = ScottPlot.MarkerShape.OpenCircle;
                MinScatter.MarkerColor = MinScatter.Color;
                MinScatter.MarkerSize = 10;
                MinScatter.LegendText = "Мин.";

                yAxisTime.LabelText = "Время (сек.)";
                yAxisTime.LabelFontColor = MinScatter.Color;

                plot.Title($"Популяция {pop} особей");
                plot.SavePng($"PopulationWithTimePlot/Pop{pop}withTime.png", 700, 500);
            }

        }

        public static double PercentageTextMatching(string original, string test)
        {
            if (original.Length == 0 || test.Length == 0)
            {
                return 0;
            }

            double cnt;

            if (original.Length >= test.Length)
            {
                cnt = test.Length;
            }
            else
            {
                cnt = original.Length;
            }

            double coincidences = 0;

            for (int i = 0; i < cnt; i++)
            {
                if (original[i] == test[i])
                {
                    coincidences++;
                }
            }

            return double.Round(coincidences / cnt, 2);
        }

        public static double PercentageKeyMatching(List<int> hOrig, List<int> vOrig, List<int> hTest, List<int> vTest)
        {
            if (hOrig.Count == 0 || vOrig.Count == 0 || hTest.Count == 0 || vTest.Count == 0)
            {
                return 0;
            }

            double hCnt, vCnt;

            if (hOrig.Count >= hTest.Count)
            {
                hCnt = hTest.Count;
            }
            else
            {
                hCnt = hOrig.Count;
            }

            if (vOrig.Count >= vTest.Count)
            {
                vCnt = vTest.Count;
            }
            else
            {
                vCnt = vOrig.Count;
            }

            double coincidences = 0;

            for (int i = 0; i < hCnt; i++)
            {
                if (hOrig[i] == hTest[i])
                {
                    coincidences++;
                }
            }

            for (int i = 0; i < vCnt; i++)
            {
                if (vOrig[i] == vTest[i])
                {
                    coincidences++;
                }
            }

            return double.Round(coincidences / (hCnt + vCnt), 2);
        }

        public static string GetTests(List<VigenereIndividual> individuals, string cryptoText, string alphabet)
        {
            if (cryptoText is null || cryptoText.Length == 0) throw new ArgumentException("Текст не может быть пустым");
            if (alphabet is null || alphabet.Length == 0) throw new ArgumentException("Алфавит не может быть пустым");

            string tests = "";

            foreach (var individual in individuals)
            {
                Vigenere.DecryptVigenere(cryptoText, individual.Key, alphabet, out string text);
                tests += PercentageTextMatching(Original5000, text).ToString(new System.Globalization.CultureInfo("en-US")) + "\t";
            }

            return tests;
        }

        public static List<double> ToDoubleList(List<string> list)
        {
            var doubles = new List<double>();

            foreach (string s in list)
            {
                if (double.TryParse(s, out double d))
                {
                    doubles.Add(d);
                }
            }
            return doubles;
        }

        public static string ListToString(List<double> doubles)
        {
            var txt = "";

            foreach(double d in doubles)
            {
                txt += d + ", ";
            }

            return txt;
        }
    }
}
